package com.ckerchina.admin.ckadmin.service;

import com.ckerchina.admin.ckadmin.dao.WxUserDAO;
import com.ckerchina.admin.ckadmin.domain.AppUser;
import com.ckerchina.admin.ckadmin.domain.WXUser;
import com.ckerchina.admin.ckadmin.service.wx.WxAccessResult;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.apache.http.client.fluent.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Date;
import java.util.UUID;

/**
 * Created by 晓丰 on 2016/1/9.
 */
@Service
public class ZhuziWxService {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${wx.app.appid}")
    String appid;
    @Value("${wx.app.secret}")
    String secret;

    @Autowired
    AppUserService appUserService;

    @Autowired
    WxUserDAO wxUserDAO;

    @Transactional
    public AppUser login(String code) throws IOException {
        WXUser wxUser = getOrCreateWxUser(getWxUser(code, appid, secret));
        
        if(wxUser.getUserid()==0){
        
            AppUser appUser=new AppUser();             
            logger.info("getNickname {},result is {}",wxUser.getNickname());
            appUser.setName(wxUser.getNickname());
            appUser.setRegTime(new Date());
            appUser.setToken(UUID.randomUUID().toString());
            appUserService.persist(appUser);
            wxUser.setUserid(appUser.getId());
            wxUserDAO.merge(wxUser);
            return appUser;
        }else{
            long userid = wxUser.getUserid();
            AppUser appUser = appUserService.find(userid);
            return appUser;
        }
    }

    private WXUser getOrCreateWxUser(WXUser wxUser) {
        WXUser dbWxUser = wxUserDAO.find(wxUser.getOpenid());
        if(dbWxUser==null){
            wxUserDAO.persist(wxUser);
            return wxUser;
        }
        return dbWxUser;
    }

    @Transactional
    public AppUser bind(String code,long userid) throws IOException {
        WXUser dbWxUser = getOrCreateWxUser(getWxUser(code, appid, secret));
        dbWxUser.setUserid(userid);
        wxUserDAO.merge(dbWxUser);
        AppUser appUser = appUserService.find(userid);
        return appUser;
    }

    private WXUser getWxUser(String code,String appid,String secret) throws IOException {
        WxAccessResult resultMap = getAuthWxAccessResult(code, appid, secret);
        String url="https://api.weixin.qq.com/sns/userinfo?access_token="+resultMap.getAccess_token()+"&openid="+resultMap.getOpenid();
        System.out.println("url:"+url);
        String userResult = new String(Request.Get(url).execute().returnContent().asBytes(),"UTF-8");
        System.out.println("userResult:"+userResult);
        logger.info("requesting {},result is {}",url,userResult);
        return new ObjectMapper().readValue(userResult, WXUser.class);
    }

    private WxAccessResult getAuthWxAccessResult(String code, String appid, String secret) throws IOException {
        String url1="https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appid+"&secret="+secret+"&code="+code+"&grant_type=authorization_code";
        String result = Request.Get(url1).execute().returnContent().asString();
        logger.info("微信认证，url is {},and result is {}",url1,result);
        WxAccessResult resultMap = new ObjectMapper().readValue(result, WxAccessResult.class);
        if(resultMap.getErrcode()!=0){
            logger.error("微信认证失败，url is {},and errorcode is {}, and errormsg is ",url1,resultMap.getErrcode(),resultMap.getErrmsg());
            throw new RuntimeException("微信认证失败"+resultMap.getErrcode()+":"+resultMap.getErrmsg());
        }
        return resultMap;
    }

    public String convertToXml(Object obj, String encoding) {
        String result = null;
        try {
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);

            StringWriter writer = new StringWriter();
            marshaller.marshal(obj, writer);
            result = writer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public <T> T converyToJavaBean(String xml, Class<T> c) {
        T t = null;
        try {
            JAXBContext context = JAXBContext.newInstance(c);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            t = (T) unmarshaller.unmarshal(new StringReader(xml));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }
    
    @Transactional
    public WXUser findByUserID(long userid) {
        return wxUserDAO.findByUserID(userid);
    }
}
